//    entity language compiler Copyright (C) 2011 Vincent Belliard

//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation version 3 of the License.

//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.

//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <typeinfo>
#include "types.h"
#include "entity.h"
#include "method.h"
#include "type.h"
#include "expression.h"
#include "global.h"

// }{--------------------------------------------------------------

void T_global::dump(FILE *file) const
{
if (constant) fprintf(file, "const ") ;
else fprintf(file, "global ") ;
fprintf(file, "%s ", name.string()) ;
if (type_expression != NULL)
	{
	fprintf(file, " : ") ;
	type_expression->dump(file) ;
	}
if (expression != NULL)
	{
	fprintf(file, " = ") ;
	expression->dump(file) ;
	}
fprintf(file, "\n") ;
}

void T_global::parse(T_entity_compiler *compiler)
{
if (!compiler->is_identifier())
	{
	compiler->add_error(compiler->location, "identifier expected.") ;
	compiler->skip_semicolon() ;
	return ;
	}
name.set(compiler->string) ;
compiler->next_item() ;
if (compiler->current_item == entity_compiler_item_colon)
	{
	compiler->next_item() ;
	type_expression = compiler->parse_expression() ;
	if (type_expression == NULL)
		{
		compiler->add_error(compiler->location, "type expected.") ;
		compiler->skip_semicolon() ;
		return ;
		}
	}
if (compiler->current_item == entity_compiler_item_equal)
	{
	compiler->next_item() ;
	expression = compiler->parse_expression() ;
	if (expression == NULL)
		{
		compiler->add_error(compiler->location, "expression expected.") ;
		compiler->skip_semicolon() ;
		return ;
		}
	}
if ((type_expression == NULL) && (expression == NULL))
	{
	compiler->add_error(compiler->location, "colon or equal expected.") ;
	compiler->skip_semicolon() ;
	return ;
	}
if (compiler->current_item == entity_compiler_item_semicolon)
	{
	compiler->next_item() ;
	}
else if (!is_block() && (compiler->current_item != entity_compiler_item_right_brace))
	{
	compiler->add_error(compiler->location, "semicolon expected.") ;
	}
}

void T_global::verify_semantic(T_entity_compiler *compiler, T_entity_program *program, T_scope *scope)
{
if (expression != NULL)
	{
	if (!expression->verify_semantic(compiler, program, scope, NULL)) return ;
	}
if (type_expression == NULL)
	{
	type = expression->type ;
	}
else if (type_expression->verify_semantic(compiler, program, scope, NULL))
	{
	type = type_expression->get_type_expression() ;
	if (type == NULL) compiler->add_error(location, "bad type for global.") ;
	}
//fprintf(stderr, "%p : %s : type=%p\n", this, name.string(), type) ;
}

void T_global::generate_declaration(FILE *file)
{
fprintf(file, "extern ") ;
type->generate_type_name(file, type_generate_instance) ;
fprintf(file, " %s ;\n", name.string()) ;
}

void T_global::generate_definition(FILE *file)
{
type->generate_type_name(file, type_generate_instance) ;
fprintf(file, " %s ;\n", name.string()) ;
}

// }{--------------------------------------------------------------
